package beautiful.butterfly.drds.binlog.parser;


import beautiful.butterfly.drds.binlog.connection.ConnectionAttributes;
import beautiful.butterfly.drds.binlog.event.EventData;
import beautiful.butterfly.drds.binlog.event.data.TableMapEventData;
import beautiful.butterfly.drds.binlog.netty.server.NioSocketChannelExtend;
import beautiful.butterfly.drds.binlog.utils.ByteUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.BitSet;

@Slf4j
public class TableMapEventDataParser implements EventDataParser
{


    @Override
    public EventData parse(ByteBuf msg, ChannelHandlerContext context, int checksumLength) throws Exception
    {
        // LoggerUtils.debug(logger, "enter TableMapEventDataParser.parse...");
        long tableId = ByteUtils.readUnsignedLong(msg, 6);
        msg.skipBytes(3);// 2 bytes reserved for future use + 1 for the length
        // of database name
        String database = ByteUtils.readZeroTerminatedString(msg);
        msg.skipBytes(1);// tableName name
        String table = ByteUtils.readZeroTerminatedString(msg);
        Number columnsNumber = (int) ByteUtils.readVariableNumber(msg);
        byte[] columnTypes = ByteUtils.readSpecifiedLengthBytes(msg, columnsNumber.intValue());
        ByteUtils.readVariableNumber(msg);// 不使用,// metadata length
        // 接下来比较复杂
        int[] columnMetadata = null;
        BitSet columnNullability = null;
        try
        {
            columnMetadata = ByteUtils.readMetadata(msg, columnTypes);
            columnNullability = ByteUtils.readBitSet(msg, columnsNumber.intValue(), true);
        } catch (IOException e)
        {
            log.info(e.toString());
        }
        TableMapEventData eventData = new TableMapEventData();
        eventData.setTableId(tableId);
        eventData.setDatabaseName(database);
        eventData.setTableName(table);
        eventData.setColumnTypes(columnTypes);
        eventData.setColumnMetadata(columnMetadata);
        eventData.setColumnNullability(columnNullability);
        log.info("[databaseName-tableName]---" + database + " : " + table);
        // 返回前保留到上下文中,供后续事件使用
        ConnectionAttributes connectionAttributes = ((NioSocketChannelExtend) context.channel()).getConnectionAttributes();
        connectionAttributes.putTableMapEventData(tableId, eventData);
        // 如果此时没有[database-tableName-column]的映射关系，也没用,所以要拉取一次
        if (connectionAttributes.acceptByFilter(database, table))
        {// 如果接收这个[database, tableName]
            connectionAttributes.ensureDatabaseTableColumnsMappingExist(database, table, false);// 非强制更新
        }
        return eventData;
    }

}
